package com.tanhua.server.service.Impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.service.MovementService;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lifeihu
 * @date 2021/12/26
 * @TIME:18:57
 */
@Service
public class MovementServiceImpl implements MovementService {
    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;
    @DubboReference
  private   UserInfoApi userInfoApi;
    @Autowired
   private RedisTemplate<String, String> redisTemplate;
    @DubboReference
    private VisitorsApi visitorsApi;

    //查询个人动态
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //1、根据用户id，调用API查询个人动态内容（PageResult  -- Movement）
        PageResult pr = movementApi.findByUserId(userId, page, pagesize);
        //2、获取PageResult中的item列表对象
        List<Movement> items = (List<Movement>) pr.getItems();
        //3、非空判断
        if (items == null) {
            return pr;
        }
        //4、循环数据列表
        UserInfo userInfo = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            //5、一个Movement构建一个Vo对象
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        //6、构建返回值
        pr.setItems(vos);
        return pr;
    }
    //查询好友动态
    @Override
    public PageResult findFriendMovents(Integer page, Integer pageSize) {
        //1.获取用户id
        Long userId = UserHolder.getUserId();
        //2.查询好友动态
        List<Movement> friendMovements = movementApi.findFriendMovements(page, pageSize, userId);
        //3、判断列表是否为空
        return getPageResult(page,pageSize,friendMovements);
    }
    /**
     * 查询推荐动态
     */
    @Override
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        //1、从redis中获取推荐数据
        String redisKey = Constants.MOVEMENTS_RECOMMEND +UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //2、判断推荐数据是否存在
        List<Movement> list = Collections.EMPTY_LIST;
        if(StringUtils.isEmpty(redisValue)){
            //3、如果不存在，调用API随机构造10条动态数据
            list = movementApi.randomMovements(pagesize);
        }else {
        //4、如果存在，处理pid数据   "16,17,18,19,20,21,10015,10020,10040,10064,10092,10093,10099,10067" 15
        String[] values = redisValue.split(",");
        //判断当前页的起始条数是否小于数组总数
        if((page -1) * pagesize<values.length){
            List<Long> pids = Arrays.stream(values).skip((page - 1) * pagesize).limit(pagesize)
                    .map(e->Long.valueOf(e))
                    .collect(Collectors.toList());
            //5、调用API根据PID数组查询动态数据
            list = movementApi.findMovementsByPids(pids);
        }}
            //6、调用公共方法构造返回值
        return getPageResult(page,pagesize,list);
    }

    @Override
    public MovementsVo findByMovementId(String id) {
        Movement movement = movementApi.findById(id);
        if(movement!=null){
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            return vo;
        }
        return null;
    }

    @Override
    public List<VisitorsVo> queryVisitorsList() {
        //1、查询访问时间
        String key=Constants.VISITORS_USER;
        String hashKey=String.valueOf(UserHolder.getUserId());
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date=StringUtils.isEmpty(value)?null:Long.valueOf(value);

        //2、调用API查询数据列表 List<Visitors>
        List<Visitors> list = visitorsApi.queryMyVisitors(date,UserHolder.getUserId());
        //3、提取用户的id
        List<Long> ids = list.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());
        //4、查看用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, null);
        //5、构造返回
        List<VisitorsVo> vos = new ArrayList<>();
        list.stream().map(c -> {
            UserInfo userInfo = map.get(c.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo, c);
                vos.add(vo);
            }
            return c;
        }).collect(Collectors.toList());
        //6.设置当前访问时间
        redisTemplate.opsForHash().put(key,hashKey,System.currentTimeMillis()+"");
        return vos;
    }


    //抽取公共方法
    public PageResult getPageResult(Integer page, Integer pagesize, List<Movement> list){
        if(CollUtil.isEmpty(list)){
            return new PageResult();
        }
       //4、提取动态发布人的id列表
        List<Long> ids = list.stream().map(Movement::getUserId).collect(Collectors.toList());
        //5、根据用户的id列表获取用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, null);
        //6、一个Movement构造一个vo对象
        List<MovementsVo> vos = new ArrayList<>();
         list.stream().map(c -> {
            UserInfo userInfo = map.get(c.getUserId());
                     if(userInfo != null) {
                         MovementsVo vo = MovementsVo.init(userInfo, c);
                         vos.add(vo);
                     }
            return c;
        }).collect(Collectors.toList());
        return  PageResult.init(page, pagesize,0l,vos);
    }
    @Autowired
    AmqpTemplate amqpTemplate;
    /**
     * 发布动态
     */
    @Override
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1. 参数校验
        if (movement == null || (StringUtils.isEmpty(movement.getTextContent()) && ArrayUtil.isEmpty(imageContent))) {
            throw new BusinessException(ErrorResult.contentError());
        }
        //2. 上传图片到阿里云
        List<String> medias = new ArrayList<>();
        if (ArrayUtil.isNotEmpty(imageContent)) {
            for (MultipartFile file : imageContent) {
                String url = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
                medias.add(url);
            }
        }
        //3. 调用dubbo服务发布动态
        Long userId = UserHolder.getUserId();
        movement.setUserId(userId);
        movement.setMedias(medias);
        movement.setState(0);

        movementApi.publish(movement);

        //发送动态审核消息
        amqpTemplate.convertSendAndReceive("tanhua.audit.exchange", "audit.movement", movement.getId().toHexString());
    }
}
